/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cuni.amis.pogamut.episodic.schemas;

import cz.cuni.amis.pogamut.episodic.decisions.Action;
import cz.cuni.amis.pogamut.episodic.decisions.AtomicAction;
import cz.cuni.amis.pogamut.episodic.decisions.Intention;
import cz.cuni.amis.pogamut.episodic.decisions.Node;
import cz.cuni.amis.pogamut.episodic.decisions.NodeType;
import cz.cuni.amis.pogamut.episodic.memory.Affordance;
import cz.cuni.amis.pogamut.episodic.memory.AgentMemory;
import cz.cuni.amis.pogamut.episodic.memory.IdGenerator;
import cz.cuni.amis.pogamut.episodic.memory.Parameters;
import cz.cuni.amis.pogamut.episodic.schemas.utils.Binomial;
import cz.cuni.amis.pogamut.episodic.episodes.Episode;
import cz.cuni.amis.pogamut.episodic.episodes.EpisodeNode;
import cz.cuni.amis.pogamut.episodic.episodes.ObjectNode;
import cz.cuni.amis.pogamut.episodic.episodes.ObjectSlot;
import org.apache.commons.collections15.multimap.MultiHashMap;
import java.util.*;

/**
 * @author Zdenek Behan
 */
public class TemporalSchema {
    // Indexed by: level, period
    // The lowest level item (0) has a periodicity of 1, and therefore acts as a global
    // schema.
    public HashMap<Integer, HashMap<Integer, MultiHashMap<Integer, SchemaCounter>>> temporalCounts = null;

    // Copy of the items in Parameters. These have to be initialized before first use.
    static int maxLevels;
    static int[] levelLengths;

    // These are calculated from the statics on creation.
    int[] periodicity;
    int[] intervalLength;

    public TemporalSchema() {
        temporalCounts = new HashMap();

        if (maxLevels == 1) {
            // HACK: the global schema must always exist, so maxLevels cannot be 1
            maxLevels = 2;
        }
        periodicity = new int[maxLevels -1];
        intervalLength = new int[maxLevels -1];

        // Temporal schemas are the same as chronobag periods, with the top and bottom levels missing.
        // Obviously, we don't need one-day temporal schema, and neither a top level one.
        temporalCounts.put(0, new HashMap());
        temporalCounts.get(0).put(0, new MultiHashMap<Integer, SchemaCounter>());
        periodicity[0] = 1;
        intervalLength[0] = 1;
        for (int i=1; i < (maxLevels - 1); i++) {
            temporalCounts.put(i, new HashMap());
            // Size and repetition of the intervals
            periodicity[i] = levelLengths[i];
            intervalLength[i] = levelLengths[i-1];

            for (int j=0; j < (periodicity[i] / intervalLength[i]); j++) {
                temporalCounts.get(i).put(j, new MultiHashMap<Integer, SchemaCounter>());
            }
        }
    }

    public MultiHashMap<Integer, SchemaCounter> getSchema() {
        return temporalCounts.get(0).get(0);
    }

    public MultiHashMap<Integer, SchemaCounter> getSchema(int level, int index) {
        if (level == 0)
            return getSchema();
        assert(level > 0);
        assert(level < (maxLevels - 1));
        // Look up the counters for a given level and offset day
        return temporalCounts.get(level).get((index % periodicity[level]) / intervalLength[level]);
    }
}
